package slave;

import java.io.IOException;
import java.net.InetAddress;

import commonUtility.XmlHandler;

import slave.SlaveComunicator;

/**
 * @author erond
 * Classe di avvio per l'unità SLAVE. Provvede ad avviare dapprima l'interfaccia per il settaggio
 * dei parametri di bootstrap, e successivamente i thread di "lavoro" SlaveStreamProvider e "comunicazione
 * il master" SlaveComunicator
 */
public class Slave implements Runnable{

	private InetAddress masterIP= null;
	/**
	 * @return the masterIP
	 */
	public InetAddress getMasterIP() {
		return masterIP;
	}

	/**
	 * @param masterIP the masterIP to set
	 */
	public void setMasterIP(InetAddress masterIP) {
		this.masterIP = masterIP;
	}

	/**
	 * @return the multicastIP
	 */
	public InetAddress getMulticastIP() {
		return multicastIP;
	}

	/**
	 * @param multicastIP the multicastIP to set
	 */
	public void setMulticastIP(InetAddress multicastIP) {
		this.multicastIP = multicastIP;
	}

	/**
	 * @return the multicastPort
	 */
	public int getMulticastPort() {
		return multicastPort;
	}

	/**
	 * @param multicastPort the multicastPort to set
	 */
	public void setMulticastPort(int multicastPort) {
		this.multicastPort = multicastPort;
	}

	/**
	 * @return the portaJob
	 */
	public int getPortaJob() {
		return portaJob;
	}

	/**
	 * @param portaJob the portaJob to set
	 */
	public void setPortaJob(int portaJob) {
		this.portaJob = portaJob;
	}

	/**
	 * @return the portaDelete_after
	 */
	public int getPortaDelete_after() {
		return portaDelete_after;
	}

	/**
	 * @param portaDeleteAfter the portaDelete_after to set
	 */
	public void setPortaDelete_after(int portaDeleteAfter) {
		portaDelete_after = portaDeleteAfter;
	}

	/**
	 * @return the portaDelete_before
	 */
	public int getPortaDelete_before() {
		return portaDelete_before;
	}

	/**
	 * @param portaDeleteBefore the portaDelete_before to set
	 */
	public void setPortaDelete_before(int portaDeleteBefore) {
		portaDelete_before = portaDeleteBefore;
	}

	private InetAddress multicastIP= null;
	private int multicastPort = 0;
	private int portaJob= 0;	
	private int portaDelete_after= 0;	
	private int portaDelete_before= 0;	
	private double weightC = 0;
	
	public void setWeightC(double weightC) {
		this.weightC = weightC;
	}

	private double weightRSSI = 0;
	public void setWeightRSSI(double weightRSSI) {
		this.weightRSSI = weightRSSI;
	}
	
	private String network = null;
	public void setNetwork(String network) {
		this.network = network;
	}

	private static XmlHandler xmlSynchronized = null;

	static SlaveStreamProvider sm = null;
	static SlaveComunicator sc = null;

	private Object semaphore = new Object();

	/**
	 * @return the semaphore
	 */
	public Object getSemaphore() {
		return semaphore;
	}
	
	public Slave() {}

	public void run() {
		
		System.out.println("SlaveThread.start() ...attendo settaggio bootstrap!");

		synchronized (semaphore) {
			try {
				semaphore.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		System.out.println("SlaveThread sbloccato! ...si comincia...");

		xmlSynchronized = new XmlHandler(weightC,weightRSSI,network);	

		/**
		 * Creo i principali thread dell'unità slave: SLAVE MANAGER e SLAVE COMUNICATOR
		 */
		sm = new SlaveStreamProvider(xmlSynchronized);
		sc = new SlaveComunicator(sm, multicastIP, multicastPort, masterIP, portaJob, portaDelete_after,portaDelete_before, xmlSynchronized);

		/**
		 * Avvio i thread SlaveStreamProvider e SlaveComunicator
		 */
		sm.setName("SlaveStreamProvider");
		sm.start();

		sc.setName("SlaveComunicator");
		sc.start();

		try {
			sc.join();
		} catch (InterruptedException e) {
			System.out.println("Eccezione...terminazione thread SlaveStreamProvider");
			e.printStackTrace();
		}
		try {
			sm.join();
		} catch (InterruptedException e) {
			System.out.println("Eccezione...terminazione thread SlaveComunicator");
			e.printStackTrace();
		}

	}//fine run()
	
	/**
	* This method should return an instance of this class which does 
	* NOT initialize it's GUI elements. This method is ONLY required by
	* Jigloo if the superclass of this class is abstract or non-public. It 
	* is not needed in any other situation.
	 */
	public static Object getGUIBuilderInstance() {
		return new Slave(Boolean.FALSE);
	}
	
	/**
	 * This constructor is used by the getGUIBuilderInstance method to
	 * provide an instance of this class which has not had it's GUI elements
	 * initialized (ie, initGUI is not called in this constructor).
	 */
	public Slave(Boolean initGUI) {
		super();
	}
	
	public static void main(String[] args) throws IOException {
		System.out.println("Avviato SLAVE main...");
		//Avvio lo slave che si metterà in wait
		Slave slave = new Slave();
		Thread slaveThread = new Thread(slave);
		slaveThread.start();
		//Avvio lo slaveSetting che sbloccherà lo slave una volta concluso il settaggio dei field
		SlaveSetting slaveSetting = new SlaveSetting("Slave bootstrap setting", slave);
		Thread slaveSettingThread = new Thread(slaveSetting);
		slaveSettingThread.start();

	}//fine main

}//fine Slave
